﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Mogre;
using MogreNewt;

namespace eqgen
{
    sealed class Engine
    {
        // Główny obiekt silnika Ogre
        public Root Root;
        // Obiekt okna, do którego Ogre będzie renderować grafikę
        public RenderWindow RenderWindow;
        // Menadżer sceny Ogre - przechowuje informacje o obiektach w postaci drzewa
        public SceneManager SceneManager;
        // Kamera Ogra - nie myl jej z klasą GameCamera
        public Camera Camera;
        // Prostokąt w którym będzie wyświetlany obraz z kamery
        public Viewport Viewport;
        // Obiekt klawiatury
        public MOIS.Keyboard Keyboard;
        // Obiekt myszy
        public MOIS.Mouse Mouse;
        // Menadżer urządzeń wejścia
        public MOIS.InputManager InputManager;
        // Główny obiekt silnika Newton
        public World NewtonWorld;
        // Debugger Newtona - rysuje siatki kolizji
        public Debugger NewtonDebugger;

        public Level CurrentLevel;

        public GameCamera GameCamera;
        public ObjectManager ObjectManager;

        int BodyId;

        Engine()
        {
        }
        //nasza instancja - prywatna, dostępna jedynie poprzez akcesor (metodę zwracającą ją)
        static Engine instance; 
 
        static Engine()
        {
            instance = new Engine();
        }
 
        // Taki akcesor jest statyczną metodą, która wywołana po raz pierwszy
        // zainicjuje statyczny konstruktor
        public static Engine Singleton
        {
            get
            {
                return instance;
            }
        }

        public void Initialise()
        {
            Root = new Root();
            ConfigFile cf = new ConfigFile();
            cf.Load("Resources.cfg", "\t:=", true);
            ConfigFile.SectionIterator seci = cf.GetSectionIterator();
 
            // Iterujemy po sekcjach
            while (seci.MoveNext())
            {
                ConfigFile.SettingsMultiMap settings = seci.Current;
                            // Iterujemy po parach typ - ścieżka
                foreach (KeyValuePair<string, string> pair in settings)
                                    // Dodajemy lokacje zasobów do silnika
                    ResourceGroupManager.Singleton.AddResourceLocation(
                        pair.Value, pair.Key, seci.CurrentKey);
            }
            
            // Próbujemy przywrócić zasoby z pliku ogre.cfg
            if (!Root.RestoreConfig())                      
            // Jeżeli się to nie powiodło, prosimy użytkownika o wybranie ustawień
            if (!Root.ShowConfigDialog())
                return;

            RenderWindow = Root.Initialise(true);           
            ResourceGroupManager.Singleton.InitialiseAllResourceGroups();

            SceneManager = Root.CreateSceneManager(SceneType.ST_GENERIC);
            Camera = SceneManager.CreateCamera("MainCamera");
                    // Wydzielamy na oknie obszar, na który trafi obraz z kamery
            Viewport = RenderWindow.AddViewport(Camera);
            Camera.NearClipDistance = 0.1f;
            Camera.FarClipDistance = 1000.0f;

            MOIS.ParamList pl = new MOIS.ParamList();
            IntPtr windowHandle;
            RenderWindow.GetCustomAttribute("WINDOW", out windowHandle);
            pl.Insert("WINDOW", windowHandle.ToString());

            InputManager = MOIS.InputManager.CreateInputSystem(pl);
 
            Keyboard = (MOIS.Keyboard)InputManager.CreateInputObject(
            MOIS.Type.OISKeyboard, false);
            Mouse = (MOIS.Mouse)InputManager.CreateInputObject(
            MOIS.Type.OISMouse, false);

            NewtonWorld = new World();
            NewtonDebugger = new Debugger(NewtonWorld);
            NewtonDebugger.Init(SceneManager);

            GameCamera = new GameCamera();
            ObjectManager = new ObjectManager();
        }

        public void Update()
        {
            GameCamera.Update();
            ObjectManager.Update();

            Keyboard.Capture();
            Mouse.Capture();
            NewtonWorld.Update(1.0f / 60.0f);
            Root.RenderOneFrame();
            // Przekazujemy kontrolę do systemu, aby program nie przestał mu odpowiadać
            WindowEventUtilities.MessagePump();
        }

        //static void Main(string[] args)
        //{
        //    Engine.Singleton.Initialise();

        //    while (true)
        //    {
        //        Engine.Singleton.Update();

        //        if (Engine.Singleton.Keyboard.IsKeyDown(MOIS.KeyCode.KC_ESCAPE))
        //            break;
        //    }
        //}

        public int GetUniqueBodyId()
        {
            return BodyId++;
        }


    }

}
